package com.uc.sdk;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Data
public abstract class TcpClient{
    private static final Logger LOGGER = LoggerFactory.getLogger(TcpClient.class);
    private String host;
    private int port = 8888;
    public Channel channel;

    final EventLoopGroup group = new NioEventLoopGroup();
    final Bootstrap b = new Bootstrap();
    ChannelFuture future;

    public TcpClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public TcpClient(String host) {
        this.host = host;
    }

    /**
     * 用户客户端编解码器的处理
     * @param ch 通道
     */
    protected abstract void initChannel(SocketChannel ch);
    public ChannelFuture connect() throws InterruptedException {
        future = b.connect(host, port);
        future.addListener((ChannelFutureListener) arg0 -> {

            this.channel = future.channel();
            ClientGroup.add(this.channel.id().asLongText(),this);
            if (future.isSuccess()) {
                LOGGER.info("连接服务器成功:{}",this);
            } else {
                LOGGER.error("连接服务器失败",future.cause());
                channel.pipeline().fireChannelInactive();
            }
        });
        future.sync();
        return future;
    }
    public TcpClient start(){
        final TcpClient tc = this;
        b.group(group).channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    // 绑定连接初始化器
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        tc.initChannel(ch);
                    }
                });
        //发起异步连接请求，绑定连接端口和host信息
        try {
            synchronized (b){
                future = connect();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    /**
     * 发送数据
     * @param msg
     */
    public void send(Object msg){
        this.channel.writeAndFlush(msg);
    }
}
